package com.lcy.struct.bTreePlus.disk.recovery.undo;

import com.alibaba.fastjson.JSONObject;
import com.lcy.struct.bTreePlus.disk.core.BPlusTreeFactory;
import com.lcy.struct.bTreePlus.disk.index.BTreeIndex;
import com.lcy.struct.bTreePlus.disk.item.TreeNode;
import com.lcy.struct.bTreePlus.disk.recovery.RecoveryCenter;

import java.util.List;

/**
 * @author lucongyang
 * @date Created in  10:21
 * @description 修改的逆向操作
 */
class UndoUpdate {

    /**
     * 生成undo日志
     *
     * @param oldIndex 主键
     * @param treeNode 全新数据
     */
    String getUndo(BTreeIndex oldIndex, TreeNode treeNode) {
        Object data = BPlusTreeFactory.findDataOnDisk(oldIndex.getIndexList());
        if (data == null) {
            return null;
        }
        TreeNode node = new TreeNode();
        node.setIndex(oldIndex);
        node.setData(data);
        try {
            String treeNodeStr = RecoveryCenter.getInstance().objectMapper.writeValueAsString(node);
            String bTreeIndexStr = RecoveryCenter.getInstance().objectMapper.writeValueAsString(treeNode.getIndex());
            return "update set " + treeNodeStr + " where id=" + bTreeIndexStr;
        } catch (Exception e) {
            throw new RuntimeException("序列化失败");
        }
    }

    void doUndo(List<String> undoStrList) {
        for (String undoStr : undoStrList) {
            int lastIndexOf = undoStr.lastIndexOf(" where id=");
            String content = undoStr.substring(11, lastIndexOf);
            String indexStr = undoStr.substring(lastIndexOf + 10);
            TreeNode treeNode = JSONObject.parseObject(content, TreeNode.class);
            BTreeIndex bTreeIndex = JSONObject.parseObject(indexStr, BTreeIndex.class);
            BPlusTreeFactory.update(bTreeIndex, treeNode);
        }
    }

    static UndoUpdate getInstance() {
        return Singleton.INSTANCE;
    }

    DoUndo.Suitable isSuit() {
        return (undoStr) -> undoStr.startsWith("update set ");
    }

    private static class Singleton {
        private static final UndoUpdate INSTANCE = new UndoUpdate();
    }

    private UndoUpdate() {
    }
}
